package kr.co.icebird.swt.app.ch5;

import java.util.LinkedList;
import java.util.List;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ExtendedModifyEvent;
import org.eclipse.swt.custom.ExtendedModifyListener;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;

public class Ch5_Undoable extends Composite {

	private static final int MAX_STACK_SIZE = 25;
	private List undoStack;
	private List redoStack;

	private StyledText styledText;

	public Ch5_Undoable(Composite parent) {
		super(parent, SWT.NONE);
		undoStack = new LinkedList();
		redoStack = new LinkedList();

		buildControls();
	}

	private void buildControls() {
		this.setLayout(new FillLayout());

		styledText = new StyledText(this, SWT.MULTI | SWT.V_SCROLL);

		styledText.addExtendedModifyListener(new ExtendedModifyListener() {

			public void modifyText(ExtendedModifyEvent event) {
				String currText = styledText.getText();
				String newText = currText.substring(event.start, event.start
						+ event.length);

				if (newText != null && newText.length() > 0) {
					if (undoStack.size() == MAX_STACK_SIZE) {
						undoStack.remove(undoStack.size() - 1);
					}
					undoStack.add(0, newText);
				}
			}
		});

		styledText.addKeyListener(new KeyAdapter() {
			public void keyPressed(KeyEvent e) {
				switch (e.keyCode) {
				case SWT.F1:
					undo();
					break;
				case SWT.F2:
					redo();
					break;
				default:
					break;
				}
			}
		});
	}

	private void redo() {
		if (undoStack.size() > 0) {
			String lastEdit = (String) undoStack.remove(0);
			int editLength = lastEdit.length();
			String currText = styledText.getText();
			int startReplaceIndex = currText.length() - editLength;
			styledText.replaceTextRange(startReplaceIndex, editLength, "");

			redoStack.add(0, lastEdit);
		}
	}

	private void undo() {

		if (redoStack.size() > 0) {
			String text = (String) redoStack.remove(0);
			moveCursorToEnd();
			styledText.append(text);
			moveCursorToEnd();
		}
	}

	private void moveCursorToEnd() {
		styledText.setCaretOffset(styledText.getText().length());
	}
}
